<!-- https://blog.csdn.net/hope_It/article/details/103266053 -->
<!-- 开发： webpack-dev-serve dev.js -->
<!-- 生产： webpack pro.js -->
<template>
  <mark-display :markdown="markdown" @title="setTitle" keyboard-ctrl url-hash-ctrl auto-font-size auto-blank-target></mark-display>
</template>

<script>
import MarkDisplay from "vue-mark-display";
const markdown = `###### 构建工具相关

----

###### 出现构建工具之前我们的开发模式
<p>通过命名空间的方式来组织代码，例如 jQuery 库把它的API都放在了 window.$ 下</p>
<p>命名空间冲突，两个库可能会使用同一个名称，例如 Zepto 也被放在 window.$ 下；</p>

----

###### 再后来 一般使用AMD、CMD、ES6、CommonJs等实现 JS模块化
<p style="font-size:30px">AMD(RequireJS) 采用异步的方式去加载依赖的模块;优点：可运行在浏览器环境和 Node.js 环境下;缺点:没有原生环境支持 AMD，需要先导入实现了 AMD 的库</p>
<p style="font-size:30px">CMD(SeaJS) 是一个同步模块定义 优点:动态加载，前端性能优化; 缺点:学习文档偏少且混乱</p>
<p style="font-size:30px">CommonJs 是通过module.exports定义的;优点：代码可复用于 Node.js 环境下并运行;缺点：无法直接在浏览器运行，必须转换成标准的 ES5</p>
<p style="font-size:30px">ES6模块化 语言的层面上实现了模块化；优点：浏览器和 Node.js原生支持；缺点：转换成标准的 ES5</p>

----

###### 为什么需要构建工具？
<p>1.复杂应用开发中的代码组织和兼容性问题</p>
<p>2.模块文件会比较多,导致请求较多</p>
<p>3.html；css；图片；字体等资源文件管理发散</p>
<p>4.项目依赖外部模块版本控制不清晰</p>

----

###### 构建工具出现后 对于我们项目解决了哪些问题？
<pre>
代码转换：TypeScript 编译成 JavaScript、SCSS 编译成 CSS 等。
文件优化：压缩 JavaScript、CSS、HTML 代码，压缩合并图片等。
代码分割：提取多个页面的公共代码、提取首屏不需要执行部分的代码让其异步加载。
模块合并：在采用模块化的项目里会有很多个模块和文件，需要构建功能把模块分类合并成一个文件。
自动刷新：监听本地源代码的变化，自动重新构建、刷新浏览器。
代码校验：在代码被提交到仓库前需要校验代码是否符合规范，以及单元测试是否通过。
自动发布：更新完代码后，自动构建出线上发布代码并传输给发布系统。
</pre>
<pre>
构建是工程化、自动化思想在前端开发中的体现；解放了我们的生产力
</pre>

----

###### 出现一系列构建工具
![avatar](http://172.16.0.155:8080/img/1632847004(1).jpg)

----

![avatar](http://172.16.0.155:8080/img/1632847107(1).jpg)

----

![avatar](http://172.16.0.155:8080/img/1632847345(1).jpg)

----

![avatar](http://172.16.0.155:8080/img/1632847542(1).jpg)

----

![avatar](http://172.16.0.155:8080/img/1632847599(1).jpg)

----

###### 为什么选择 Webpack
<pre>
大多数团队在开发新项目时会采用紧跟时代的技术，这些技术几乎都会采用“模块化+新语言+新框架”，
Webpack 可以为这些新项目提供一站式的解决方案；
Webpack 有良好的生态链和维护团队，能提供良好的开发体验和保证质量；
Webpack 被全世界的大量 Web 开发者使用和验证，能找到各个层面所需的教程和经验分享。
</pre>

----

###### <p>开发模式利用webpack-dev-server  是一个小型Express服务器，提供web服务</p>

![avatar](http://172.16.0.155:8080/img/20191126220911383.png)

----

![avatar](http://172.16.0.155:8080/img/122.jfif)

----


![avatar](http://172.16.0.155:8080/img/1632928754(1).png)



----

###### 入口 出口 
构建其内部 依赖图(dependency graph) 的开始。进入入口起点后，webpack 会找出有哪些模块和库是入口起点（直接和间接）依赖的
<pre align="left" style="font-size: 30px;">
// JS 执行入口文件
  entry: {
    main: './main.js',
  },
  output: {
    // 为从 entry 中配置生成的 Chunk 配置输出文件的名称
    filename: '[name].js',
    // 为动态加载的 Chunk 配置输出文件的名称
    chunkFilename: '[name].js',
  }
</pre>

----

###### Webpack Loader 基本的加载器
<p style="font-size: 30px;">webpack默认只识别js结尾的文件,当遇到其他格式的文件后,webpack并不知道如何去处理。这时候就要用loader了</p>
<p style="font-size: 30px;">Loader 就像一个翻译员且职责是单一的，能将源文件(LESS；sass；es6+；图片)经过转化后输出新的结果，并且一个文件还可以链式地经过多个翻译员翻译。</p>

<p>
比如：vue-loader这个加载器将SFCs(单文件组件)语言块分割开来，并将每个块通过管道传输到一个适当的加载器，
例如脚本块传输到babel-loader，样式块传输sass/css/style-loader，而模板块传输Vue-template-loader，后者将模板转换成JavaScript呈现函数。
vue-loader的最终输出是一个JavaScript模块，可以包含在您的Webpack包中。
</p>


----

###### 一个文件可以链式地经过多个翻译员翻译
![avatar](http://172.16.0.155:8080/img/1632763663(1).jpg)

----

###### Webpack Plugin 基本的插件
<pre style="font-size: 30px;">
webpack构建流程中的特定时机会广播出对应的事件，插件在监听到感兴趣的事件后会执行特定的逻辑
插件分为内部自带插件，外部插件
</pre>
<pre style="font-size: 30px;">
const HtmlWebpackPlugin = require('html-webpack-plugin');
{
	plugins: [
	   new webpack.ProgressPlugin(),
	   new HtmlWebpackPlugin({template: './src/index.html'})
	 ]
}
</pre>
<p style="font-size: 30px;">1.html-webpack-plugin（生成一个html文件，引入构建后如script、link并动态添加hash）</p>
<p style="font-size: 30px;">2.mini-css-extract-plugin （可以提取CSS到单独的文件中）</p>
<p style="font-size: 30px;">3.hard-source-webpack-plugin（构建的module进行缓存，二次构建的时候，提升构建速度）</p>

----

###### 开发模式常用插件
<p style="font-size: 30px;">1.HMR 热更新 (修改代码重新打包，并将新的模块发送到浏览器，浏览器通过新的模块替换老的模块；不刷新浏览器，状态不会丢失)</p>
<p style="font-size: 30px;">2.Live reload 实时重载 (监控文件的变化,通知浏览器端刷新页面,导致状态会丢失) </p>

----

<h6><a href="https://segmentfault.com/a/1190000020310371">热更新原理HRM</a></h6>
<pre>
Server端使用webpack-dev-server去启动本地服务，内部实现主要使用了webpack、express、websocket。

使用express启动本地服务，当浏览器访问资源时对此做响应。
服务端和客户端使用websocket实现长连接

webpack监听源文件的变化，即当开发者保存文件时触发webpack的重新编译。
每次编译都会生成hash值、已改动模块的json文件、已改动模块代码的js文件
编译完成后通过websocket-serve向客户端推送当前编译的hash戳

客户端的websocket监听到有文件改动推送过来的hash戳，会和上一次对比
一致则走缓存
不一致则通过ajax和jsonp向服务端获取最新资源

使用内存文件系统去替换有修改的内容实现局部刷新
</pre>

----

###### 生产模式常用插件 （更小，更快 ）
<p style="font-size: 30px;">1.compression-webpack-plugin 开启gzip压缩；服务器开启gzip_static后会寻找.gz直接返回；也可以用服务器压缩，但会消耗服务器性能</p>
<p style="font-size: 30px;">2.optimize-css-assets-plugin js压缩混淆；</p>
<p style="font-size: 30px;">3.webpack-bundle-analyzer；查看打包后所有组件与组件间的依赖关系，针对多余的包文件过大 可以进行优化， </p>

----
###### 生产模式输出代码优化
<p>1.对资源进行压缩;减少体积; file-loader </p>
<p>2.减少http请求;图片转换为base64; url-loader</p>
<p>3.svg图片;合成雪碧图; svg-sprite-loader</p>
<p>4.CSS剥离与压缩; mini-css-extract-plugin</p>
<p>5.合并公共业务代码/node_modules代码 webpack.optimize.CommonsChunkPlugin，和业务解耦后;利用浏览器缓存提升加载速度 </p>
<p>6.代码分割，按需加载; 功能代码分类</p>
<p>7.Tree-shaking 消除无用的js代码</p>

----

###### 代码分割方式-异步组件或路由
<pre>
		components:{
			//异步组件需要被渲染的时候才会触发该函数，且会把结果缓存起来供未来重渲染
			'my-component': () => import('./my-async-component')
		},
		
		routes: [
		   {
		     path: '/',
		     name: 'HomePage',
		     component:() => import('./HomePage.vue')
		   }
		 ]
</pre>

-----

###### Tree-shaking
![avatar](https://p1-jj.byteimg.com/tos-cn-i-t2oaga2asx/gold-user-assets/2018/1/4/160bfdcf2a31ce4a~tplv-t2oaga2asx-watermark.awebp)


----

###### 异步组件或路由效果
![avatar](http://172.16.0.155:8080/img/企业微信截图_16328132702191.png)

----

###### 合并node_modules依赖效果
![avatar](http://172.16.0.155:8080/img/企业微信截图_16328134133111.png)

----

###### 提高开发或生产构建速度
<p>1.缩小编译范围，减少不必要的编译工作，即 modules、mainFields、noParse、includes、exclude、alias等。</p>
<p>2.通过 externals 配置来提取常用库，引用cdn加速。</p>
<p>3.使用hard-source-webpack-plugin缓存构建；cache-loader或webpack5自带缓存功能。(DllPlugin配置复杂被vue/cli,react/cli抛弃)</p>
<p>4.运行在 Node.js 之上的 Webpack 是单线程模型；但HappyPack把任务分解给多个子进程去并发的执行</p>

----

###### 使用hard-source-webpack-plugin
![avatar](http://172.16.0.155:8080/img/1632763498(1).jpg)

----

![avatar](http://172.16.0.155:8080/img/企业微信截图_16329150435800.png)

----

###### 总结
<pre style="text-align:center">善于借助和总结他人的经验更快地得出最优结果，而不是自己闷头重新探索。</pre>

`


export default {
  components: { MarkDisplay },
  data() {
    return { markdown};
  },
  methods: {
    setTitle({ title }) {
      document.title = title;
    },
  }
};
</script>

<style>
body {
  margin: 0;
  overflow: hidden;
}
p{
	margin: 15px 0;
	font-size: 30px;
	text-align: left;
	width: 100%;
}
p img{
	margin: 0 auto;
	display: block;
}
h1,h2,h3,h4,h5,h6{
	margin: 25px 0;
}
img{
	max-width: 100%;
}
pre{
	text-align: left;
	font-size: 30px;
}
</style>